<template>
  <div class="singer" ref="singer">
    <!-- 使用listview通讯录列表组件 -->
    <!-- 从子组件接收到了事件和参数 -->
    <list-view @select="selectSinger" :data="singers" ref="list"></list-view>
    <!-- 子路由 -->
    <router-view></router-view>
  </div>
</template>

<script>
// 引入getSingerList获取数据的方法
import {getSingerList} from 'api/singer'
// 前面定义了一个常量ERR_OK=0引入进来，这样设置，便于以后修改
import {ERR_OK} from 'api/config'
// 引入构造函数Sing
import Singer from 'common/js/singer'
// 把listview通讯录列表组件引入
import ListView from 'base/listview/listview'
// vuex的语法糖mapMutations
import {mapMutations} from 'vuex'
// 引入mixin.js
import {playlistMixin} from 'common/js/mixin'
// 设置一个变量，便于在函数外部维护
const HOT_NAME = '热门'
// 设置一个变量，便于在函数外部维护
const HOT_SINGER_LEN = 10

export default {
  mixins: [playlistMixin],
  data () {
    return {
      // 给获取的后端数据一个容器
      singers: []
    }
  },
  // 实例vue的选项数据都加载后调用的生命周期钩子
  created () {
    // 调用服务端获取的数据
    this._getSingerList()
  },
  methods: {
    // mixin里面handlePlaylist方法
    handlePlaylist (playlist) {
      const bottom = playlist.length > 0 ? '60px' : ''
      this.$refs.singer.style.bottom = bottom
      // 这个调用子组件的方法，不需要$el
      this.$refs.list.refresh()
    },
    // 点击路由跳转函数
    selectSinger (singer) {
      // 路由编程式
      this.$router.push({
        // 用了拼接地址
        path: `/singer/${singer.id}`
      })
      // 调用vuex语法糖,
      this.setSinger(singer)
    },
    // 给getSingerList自定义获取后端的数据方法一个包装
    _getSingerList () {
      getSingerList().then((res) => {
        if (res.code === ERR_OK) {
          // 把获取的数据放在singers
          this.singers = this._normalizeSinger(res.data.list)
        }
      })
    },
    // 因为获取的数据结构不是我们想要的，我们有两个要求，第一个十条热门，第二个同字母开头的放一起，用_norramlizeSinger来写,参数是获取的list即this.singers。得出一个我们需要的对象map,然后把map对象变成一个有序的数组
    _normalizeSinger (list) {
      // 因为要热门的，我们设置一个对象作为热门收集的数据
      let map = {
        hot: {
          title: HOT_NAME,
          // 这个是装数据的
          items: []
        }
      }
      // 要取出需要的数据啊，那么就遍历后台返回的数据，list是数组
      list.forEach((item, index) => {
        // 取返回数据的前十条，添加到items中
        if (index < HOT_SINGER_LEN) {
          // 使用arr数组的内置函数push
          map.hot.items.push(new Singer({
            // 需要返回数据中数据的是id,mid,name
            name: item.Fsinger_name,
            id: item.Fsinger_mid
          }))
        }
        // 把原数据中每一项Findex中放在key变量中
        const key = item.Findex
        // 当设置的map中没有这个key所包含的字符串属性时
        if (!map[key]) {
          // 在map对象中创建key具体内容的属性，其内容是个对像
          map[key] = {
            // 命名
            title: key,
            // 具体内容
            items: []
          }
        }
        // 有了对应的属性后，就在对应属性中的items数组中添加对应的id，name，mid
        map[key].items.push(new Singer({
          // 需要返回数据中数据的是id,mid,name
          name: item.Fsinger_name,
          id: item.Fsinger_mid
        }))
      })
      // 为了得到map的有序列表，因为遍历map的时候，不是有序的
      // 用hot和ret数组分别装下map的每项属性，最后把map对象变成一个有序的数组
      let hot = []
      let ret = []
      // 遍历这个map对象
      for (let key in map) {
        // 方便维护，减少开销用了val变量装每一项属性
        let val = map[key]
        // 如果这个字符串有a到z或者A到Z的字母，那么就把加在ret数组里面,用到了正则表达式
        if (val.title.match(/[a-zA-Z]/)) {
          ret.push(val)
        // 如果字符串是'热门'，那么就加到hot数组里面
        } else if (val.title === HOT_NAME) {
          hot.push(val)
        }
      }
      // 把ret数组排序,使用数组内置函数，sort()
      ret.sort((a, b) => {
        // 使用字符串内置函数charCodeAt(),用字符对应的编码相减比大小
        return a.title.charCodeAt(0) - b.title.charCodeAt(0)
      })
      // 在把hot数组和ret数组合并,使用数组concat()方法
      return hot.concat(ret)
    },
    // vuex的mapMutations语法糖,做一个对象映射
    ...mapMutations({
      // 这个setSinger就是这个实例的一个方法了
      setSinger: 'SET_SINGER'
    })
  },
  components: {
    ListView
  }
}
</script>

<style scoped lang="stylus" rel="stylesheet/stylus">
  .singer
    position: fixed
    top: 88px
    bottom: 0
    width: 100%
</style>
